package util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;



public class DBHelper {
	/**
	* 数据库地址URL 
	* jdbc:mysql://[数据库服务器域名或ip]:[port]/[database]
	*/
	private static final String URL = 
			"jdbc:mysql://localhost:3306/employee?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
	private static final String USER = "root";
	private static final String PASS = "root";

	//数据库连接类
	static Connection conn = null;
	//编译和执行SQL语句的对象
	static PreparedStatement ps = null;
	//接收查询返回的结果集
	static ResultSet rs = null;
	
	/*
	 * <T>声明此方法持有一个泛型T，也可以理解为此方法为一个泛型方法
	 * List<T>声明此方法的返回值类型是一个list集合，且集合中的元素类型是泛型T类型
	 * Class<T>指明泛型T的类型
	 * Object...表明该方法有多个Object类型的参数
	 */
	public static <T> List<T> query (String sql, Class<T> cls, Object... params){
		try {
			//编译SQL语句，返回prepareStatement对象
			ps = conn.prepareStatement(sql);
			//参数替换sql中的占位符
			if (params != null) {
				for (int i = 0; i < params.length; i++) {
					//占位符顺序从1开始
					ps.setObject(i+1, params[i]);
				}
			}
			//执行SQL语句，结果集封装给ResultSet
			rs = ps.executeQuery();
			//检索resultSet对象中的列数、类型和字段
			ResultSetMetaData rsd = rs.getMetaData();
			List<T> list = new ArrayList<T>();
			
			while(rs.next()) {
				//泛型实例化
				T t = cls.newInstance();
				//获取列数，（每行的字段数量）
				int count = rsd.getColumnCount();
				
				for (int i = 0; i < count; i++) {
					//获取指定列的别名，如果SQL中没有指定别名，则返回值与getColumnName()相同
					String column = rsd.getColumnLabel(i+1);
					//获取字段值
					Object value = rs.getObject(column);
					try {
						//获取Field属性对象
						Field field = cls.getDeclaredField(convertName(column));
						//开启访问权限
						field.setAccessible(true);
						//变量赋值
						field.set(t, value);
					} catch (NoSuchFieldException e) {
						e.printStackTrace();
					}
				}
				list.add(t);
			}
			return list;
		} catch (Exception e) {
			return null;
		}
	}
	//1 建立连接
	public static void conn() {

		if(conn == null) {
			//注册数据库连接驱动，反射获取连接驱动类，根据包路径加载连接驱动类
			try {
				Class.forName("com.mysql.cj.jdbc.Driver");
				//建立连接
				conn = DriverManager.getConnection(URL, USER, PASS);
//				System.out.println("数据库连接成功！");
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	//关闭链接
	public static void close() {
		try {
			if (conn != null) conn.close();
			if (ps != null)ps.close();
			if (rs != null)rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	//下划线转驼峰user_name--->userName
	public static String convertName(String column) {
		String[] arr = column.split("_");
		StringBuffer sf = new StringBuffer();
		for (int i = 0; i < arr.length; i++) {
			if (i == 0 ) {
				sf.append(arr[i]);
				continue;
			}
			String firstStr = String.valueOf(arr[i].charAt(0)).toUpperCase();
			sf.append(firstStr).append(arr[i].substring(1));
		}
		return sf.toString();
	}

	//insert,update,delete
	public static int execute(String sql,Object...params){
		
		try {
			//编译SQL语句，返回prepareStatement对象
			ps = conn.prepareStatement(sql);
			//参数替换sql中的占位符
			if (params != null) {
				for (int i = 0; i < params.length; i++) {
					//占位符顺序从1开始
					ps.setObject(i+1, params[i]);
				}
			}
			//executeUpdate()可以执行DML语句（insert,update,delete），返回执行SQL影响的行数
			int count =0;
			count = ps.executeUpdate();
			return count;
		} catch (SQLException e) {
			System.out.println("数据库方法操作错误");
			e.printStackTrace();
			return 0;
		}
		
	}

	public static List<Object> query(String sql){
		try {
//			System.out.println(sql);
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();
			List<Object> list = new ArrayList<Object>();
			while (rs.next()) {
				list.add(rs.getObject(1));
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	//插入同时返回主键
	public static Integer addReturnPK(String sql,Object...params){
		try {
			//设置执行完插入操作后需要返回主键
			ps = conn.prepareStatement(sql, ps.RETURN_GENERATED_KEYS);
			//参数替换sql中的占位符
			if (params != null) {
				for (int i = 0; i < params.length; i++) {
					//占位符顺序从1开始
					ps.setObject(i+1, params[i]);
				}
			}
			int count = ps.executeUpdate();
			//如果返回值= 0表示执行SQL影响的行数为0
			if (count == 0) return null;
			//获取新插入记录的主键
			ResultSet rs = ps.getGeneratedKeys();
			Integer id = null;
			if (rs.next()) {//遍历结果集，向下读一行数据
				//获取第一个字段的值
				id = rs.getInt(1);
			}
			return id;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

}
